package com.dq.proxy;

import com.dq.common.Invocation;
import com.dq.common.URL;
import com.dq.loadbalance.LoadBalance;
import com.dq.protocol.HttpClient;
import com.dq.register.MapRemoteRegister;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName ProxyFactory
 * @Description 远程方法调用    获取代理接口的实例对象  1. 本地
 * @Author DuX1aoQiang
 * @Date 2023/5/24 17:50
 * @Version 1.0
 */
public class ProxyFactory {

    public static <T> T getProxy(Class interfaceClass) {
        //用户配置
        Object instance = Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class[]{interfaceClass}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) {

                //配置VM 虚拟机
                String mock = System.getProperty("mock");
                if (mock != null && mock.startsWith("return:")) {
                    return mock.replace("return:", "");
                }


                //把Invocation发送出去
                Invocation invocation = new Invocation(interfaceClass.getName(), method.getName(),
                        method.getParameterTypes(), args);

                HttpClient httpClient = new HttpClient();


                //采用的本地注册实现发送
//                String result = httpClient.send("localhost", 8080, invocation);

                //采用远程服务实现发送  自己实现策略
                List<URL> urlList = MapRemoteRegister.get(interfaceClass.getName());
                //避免重复负载均衡
                List<URL> invokedUrls = new ArrayList<>();
                //服务重试 利用while
                int max = 3;
                String result = null;

                while (max > 0) {

                    //负载均衡
                    urlList.remove(invokedUrls);
                    URL url = LoadBalance.random(urlList);
                    invokedUrls.add(url);
                    try {
                        result = httpClient.send(url.getHostname(), url.getPort(), invocation);
                    } catch (Exception e) {

                        if (max-- != 0) continue;

                        //自定义报错 可以实现你自定义的容错机制
                        return "服务停止 报错了";
                    }
                }
                return result;

            }
        });
        return (T) instance;
    }
}
